Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AP_ExternalControl: initial implementation of external control library #24549

Merged
merged 7 commits into from Aug 22, 2023

Conversation

tridge
Copy link
Contributor

@tridge tridge commented Aug 9, 2023

This is a very basic implementation of an external control library, just to unblock @pedro-fuoco

Relates to #23363

Testing Instructions

  1. Run sim_vehicle with --enable-dds --console --map

  2. Set DDS_ENABLED param to 1

  3. Use mavproxy to arm the vehicle, set the mode to guided, and takeoff to ~50m

  4. Run the microROS agent like normal

  5. Verify with ros2 CLI that you see the ap/cmd_vel topic

  6. Publish commands to ap/cmd_vel, or use rqt. Current behavior is this

    # Go up at 1 m/s
    ros2 topic pub /ap/cmd_vel geometry_msgs/msg/TwistStamped '{twist: {linear: {z: 1.0}}}'
    # Go down at 2 m/s
    ros2 topic pub /ap/cmd_vel geometry_msgs/msg/TwistStamped '{twist: {linear: {z: -1.0}}}'
    # Go east at 1 m/s
    ros2 topic pub /ap/cmd_vel geometry_msgs/msg/TwistStamped '{twist: {linear: {x: 1.0}}}'
    # Rotate the quadcopter 180 degrees and repeat the above tests. Regardless of the orientation, x always makes the copter go north because the cmd_vel topic is odom frame ENU.
    

    We do need to decide if the cmd_vel topic should be in body frame or map frame. According to REP-147, the cmd_vel topic i in body frame. Perhaps we should use the frame ID to either body or map for these different ones? Or a different topic? We have to decide based on clarity (topics are easier to notice than frame ID's), but additional subscribers impact flash, code size, and RAM/CPU usage. https://ros.org/reps/rep-0147.html#rate-interface

/*
set linear velocity and yaw rate. Pass NaN for yaw_rate_rads to not control yaw
velocity is in earth frame, NED, m/s
*/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also say the frame convention for yaw rate? Even @lthall has realized the mavlink API's are not quite cut and dry. Although I don't recommend reading too much of this thread, this comment is useful.
mavlink/mavlink#2013 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh, I am going to put a PR in to fix this mistake. Once I saw it I wonder why I missed it the first time.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Please tag me, so we can follow the same convention here.

Comment on lines 471 to 476
Vector3f linear_velocity {
float(rx_velocity_control_topic.twist.linear.y),
float(rx_velocity_control_topic.twist.linear.x),
float(-rx_velocity_control_topic.twist.linear.z) };
const float yaw_rate = -rx_velocity_control_topic.twist.angular.z;
external_control->set_linear_velocity_and_yaw_rate(linear_velocity, yaw_rate);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are the test results for the frame orientations:
Positive x (correctly went East):
x_pos
Positive y (correnctly went North):
y_pos
Negative z (Wrongfully went Up):
z_negative
Positive Yaw (correctly went CounterClockwise looking from above):
yaw_pos

Thus, simply changing the linear z axis should solve it.

Suggested change
Vector3f linear_velocity {
float(rx_velocity_control_topic.twist.linear.y),
float(rx_velocity_control_topic.twist.linear.x),
float(-rx_velocity_control_topic.twist.linear.z) };
const float yaw_rate = -rx_velocity_control_topic.twist.angular.z;
external_control->set_linear_velocity_and_yaw_rate(linear_velocity, yaw_rate);
Vector3f linear_velocity {
float(rx_velocity_control_topic.twist.linear.y),
float(rx_velocity_control_topic.twist.linear.x),
float(rx_velocity_control_topic.twist.linear.z) };
const float yaw_rate = -rx_velocity_control_topic.twist.angular.z;
external_control->set_linear_velocity_and_yaw_rate(linear_velocity, yaw_rate);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also tested to see if the frame orientations were consistent with #23541. Everything except the z linear axis is perfect

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are the test results for the frame orientations: Positive x (correctly went East): x_pos Positive y (correnctly went North): y_pos Negative z (Wrongfully went Up): z_negative Positive Yaw (correctly went CounterClockwise looking from above): yaw_pos

Thus, simply changing the linear z axis should solve it.

This negative for Z should go in the copter API. The external AHRS said positive Z is down, and copter implements it differently.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This negative for Z should go in the copter API. The external AHRS said positive Z is down, and copter implements it differently.

Yes, we should definatly be using NED where positive Z is down. It can get a bit mixed up because positive altitude is up and I have not converted the position controller to NED yet but I have done most of the work in the background to make that happen. I intend it to be done by the time we fix the units.

Copy link
Collaborator

@Ryanf55 Ryanf55 Aug 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggestion from Pedro would solve it for Copter but break other vehicles. I have added a negative in the Copter implementation in this commit, as well as a comment why.
b4251a1

If/When copter transitions to NED for velocity control, the interface in AP_ExternalControl will not change, because it's already NED.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedro-fuoco In my testing, I see positive X going west.
image

@Ryanf55
Copy link
Collaborator

Ryanf55 commented Aug 10, 2023

After taking a deeper review:

  1. How should the API handle if the user commands a higher velocity than the aircraft is configured to do?
  2. Is this API method valid for rover and plane? Probably not...
  3. Should there be a define around the code to enable it?

@Ryanf55
Copy link
Collaborator

Ryanf55 commented Aug 11, 2023

After some discussion with @lthall and Steve (lead of ROS2 navigation framework), and reading REP147, we're put in an interesting position.

  1. REP-147 recommends body frame control, and says that rovers used earth frame, but it was less flexible. The second part seems out of date give 2. The command is a body relative set of velocities in linear and angular space. This diverges from the common geometry_msgs/Twist [[26]](https://ros.org/reps/rep-0147.html#twist) used by ground robots. A pure Twist based inteface could be provided for backwards compatability as well. It was chosen to diverge here since this is a much more powerful inteface for the vehicles and does not require all commands to be reverse calculated for the instantaneous attitude of the vehicle.
  2. NAV2 uses body frame control
  3. ArduCopter uses earth frame control because the math has to compensate for gravity. From Leonard: Practically, control is always done in the earth frame because gravity forces the vertical to be handled differently to the horizontal.
  4. In ROS, the translation from map to base_link is not guaranteed to be consistent, but ArduPilot has a way to deal with this.

Given these conflicts, we decided the following is a best approach for the first PR:

  1. This PR will be left as-is because earth-frame control works great on copter and is easy to understand.
  2. You are required to set the frame_id to map to use ROS 2 earth frame control in ArduPilot.
  3. We can choose to implement other vehicles or body-frame control based on user's interest.
  4. Rhys and I want some time to set up some test infrastructure before we get too far down road adding all the features.

}


#endif // AP_DDS_ENABLED
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing newline.

Copy link
Contributor

@pedro-fuoco pedro-fuoco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just re-tested everything with the ros2 cli. ENU is being followed perfectly and it is nice to filter the messages by frame_id (in this case, ignoring everything that isn't "map" frame). It will make the body-frame version of this easier to implement.

The command I used to test it was:

ros2 topic pub /ap/cmd_vel geometry_msgs/msg/TwistStamped '{header: {frame_id: "map"}, twist: {linear: {x: 1}}}'

LGTM!

tridge and others added 3 commits August 17, 2023 19:48
Signed-off-by: Ryan Friedman <ryanfriedman5410+github@gmail.com>
Co-authored-by: Andrew Tridgell <tridge60@gmail.com>
Signed-off-by: Ryan Friedman <ryanfriedman5410+github@gmail.com>
Co-authored-by: Andrew Tridgell <tridge60@gmail.com>
@tridge tridge added MergeOnCIPass and removed WIP labels Aug 21, 2023
tridge and others added 4 commits August 21, 2023 17:11
Signed-off-by: Ryan Friedman <ryanfriedman5410+github@gmail.com>
Co-authored-by: Andrew Tridgell <tridge60@gmail.com>
Signed-off-by: Ryan Friedman <ryanfriedman5410+github@gmail.com>
@tridge tridge merged commit d76bf32 into ArduPilot:master Aug 22, 2023
81 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

7 participants